package cn.com.libertymutual.sp.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.libertymutual.core.util.Constants;
import cn.com.libertymutual.core.util.DateUtil;
import cn.com.libertymutual.core.util.ListUtil;
import cn.com.libertymutual.core.web.ServiceResult;
import cn.com.libertymutual.sp.bean.TbSpApprove;
import cn.com.libertymutual.sp.bean.TbSpFlow;
import cn.com.libertymutual.sp.bean.TbSpFlowDetail;
import cn.com.libertymutual.sp.dao.ApproveDao;
import cn.com.libertymutual.sp.dao.FlowDao;
import cn.com.libertymutual.sp.dao.FlowDetailDao;
import cn.com.libertymutual.sp.service.api.FlowService;
import cn.com.libertymutual.sys.bean.SysCodeNode;
import cn.com.libertymutual.sys.dao.ISysCodeNodeDao;
import cn.com.libertymutual.sys.dao.ISysUserDao;

@Service("flowService")
public class FlowServiceImpl implements FlowService {

	@Autowired
	private FlowDao flowDao;
	@Autowired
	private FlowDetailDao flowDetailDao;
	@Autowired
	private ISysUserDao iSysUserDao;
	@Autowired
	private ISysCodeNodeDao codeNodeDao;
	@Autowired
	private ApproveDao approveDao;
	private Logger log = LoggerFactory.getLogger(getClass());

	@Transactional
	@Override
	public ServiceResult addFlow(TbSpFlow flow) {
		ServiceResult sr = new ServiceResult();
		if (StringUtils.isNotBlank(flow.getFlowType())) {
			TbSpFlow dbflow = flowDao.findByType(flow.getFlowType());
			if (null != dbflow) {
				sr.setFail();
				sr.setResult("已存在该类型的审批流！");
				return sr;
			}
		}
		String flowNo = "FW" + DateUtil.dateFromat(new Date(), DateUtil.DATE_TIME_PATTERN4);
		flow.setCreateTime(new Date());
		flow.setFlowNo(flowNo);
		flow.setStatus(Constants.TRUE);
		String flowNode = "ND" + ListUtil.doRandom();
		flow.setLastFlowNode(flowNode);
		flowDao.save(flow);
		TbSpFlowDetail detail = new TbSpFlowDetail();
		detail.setCreateTime(new Date());
		detail.setUserCode("初始节点");
		detail.setFlowName(flow.getcName());
		detail.setFlowNo(flowNo);
		detail.setParentNode("firstNode");
		detail.setFlowNode(flowNode);
		flowDetailDao.save(detail);
		SysCodeNode sysCoden = new SysCodeNode();
		sysCoden.setCodeType("APPROVEFLOW");
		sysCoden.setCode(flowNo);
		sysCoden.setCodeCname(flow.getcName());
		sysCoden.setCodeEname(flow.getFlowType());
		sysCoden.setValidStatus(Constants.TRUE);
		sysCoden.setSerialNo(1);
		codeNodeDao.save(sysCoden);

		return sr;
	}

	@Override
	public ServiceResult flowList(int pageNumber, int pageSize) {
		ServiceResult sr = new ServiceResult();
		Sort sort = new Sort(Direction.DESC, "id");

		Page<TbSpFlow> page = flowDao.findAll(new Specification<TbSpFlow>() {
			@Override
			public Predicate toPredicate(Root<TbSpFlow> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

				List<Predicate> predicate = new ArrayList<Predicate>();
				Predicate[] pre = new Predicate[predicate.size()];
				return query.where(predicate.toArray(pre)).getRestriction();
			}
		}, PageRequest.of(pageNumber - 1, pageSize, sort));
		sr.setResult(page);
		return sr;
	}

	@Override
	public ServiceResult addChildNode(TbSpFlowDetail flowDetail) {
		ServiceResult sr = new ServiceResult();
		List<TbSpApprove> tsa = approveDao.findByFlowType(Constants.APPROVE_WAIT,flowDetail.getFlowNo());
		if (CollectionUtils.isNotEmpty(tsa)) {
			sr.setFail();
			sr.setResult("该审批流存在待审批记录！");
			return sr;
		}
		String flowNode = "ND" + ListUtil.doRandom();
		if (null == flowDetail.getId()) {
			TbSpFlow flow = flowDao.findByFlowNo(flowDetail.getFlowNo());
			flowDetail.setFlowNode(flowNode);
			flowDetail.setFlowName(flow.getcName());
			flowDetail.setCreateTime(new Date());
			flowDetailDao.save(flowDetail);
			flow.setLastFlowNode(flowNode);
			flow.setUpdateTIime(new Date());
			flowDao.save(flow);
		} else {
			flowDetailDao.save(flowDetail);
		}
		
		return sr;
	}

	@Override
	public ServiceResult flowChildNodeList(String flowNo) {
		ServiceResult sr = new ServiceResult();
		// 首先找到最上层节点
		List<TbSpFlowDetail> details = flowDetailDao.findByParentNode(flowNo, "firstNode");
		if (CollectionUtils.isNotEmpty(details)) {
			List<TbSpFlowDetail> back = treeNode(details);

			sr.setResult(back);
		}
		return sr;
	}

	public List<TbSpFlowDetail> treeNode(List<TbSpFlowDetail> details) {

		for (TbSpFlowDetail detail : details) {
			if (StringUtils.isNotBlank(detail.getUserCode())) {
				if ("firstNode".equals(detail.getParentNode())) {
//					detail.setUsername(detail.getFlowName());
					detail.setUsername(detail.getUserCode());
				} else {
					String[] ss = detail.getUserCode().split("&");
					StringBuilder build = new StringBuilder();
					for (String s : ss) {
						String name = iSysUserDao.findByUserid(s).getUsername();
						log.info(name);
						build.append(name + "&");
					}
					String usernames = build.toString();
					detail.setUsername(usernames.substring(0, usernames.length() - 1));
				}
			}
			List<TbSpFlowDetail> nextDetails = flowDetailDao.findByParentNode(detail.getFlowNo(), detail.getFlowNode());
			if (CollectionUtils.isNotEmpty(nextDetails)) {
				detail.setNextNodes(nextDetails);
			}
			treeNode(nextDetails);
		}

		return details;
	}

	@Override
	public ServiceResult nodeDetail(String flowNo, String flowNode) {
		ServiceResult sr = new ServiceResult();
		sr.setResult(flowDetailDao.findByNoAndNode(flowNo, flowNode));
		return sr;
	}

	@Transactional
	@Override
	public ServiceResult removeNode(String flowNo, String flowNode) {
		ServiceResult sr = new ServiceResult();
		TbSpFlowDetail thisNode = flowDetailDao.findByNoAndNode(flowNo, flowNode);
		//看是否存在下级节点，若不存在则直接删除，
		List<TbSpFlowDetail> nextNodes = flowDetailDao.findByParentNode(flowNo, flowNode);
		if (CollectionUtils.isEmpty(nextNodes)) {
			flowDetailDao.deleteById(thisNode.getId());
			sr.setSuccess();
		}else {
			TbSpFlowDetail nextNode = nextNodes.get(0);
			nextNode.setParentNode(thisNode.getParentNode());
			flowDetailDao.save(nextNode);
			flowDetailDao.deleteById(thisNode.getId());
			sr.setSuccess();
		}
		return sr;
	}


}
